package com.awakensoftware.hunterserver.services;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.awakensoftware.hunterserver.exceptions.entityexceptions.EntityException;
import com.awakensoftware.hunterserver.exceptions.entityexceptions.EntityValidationFailureException;
import com.awakensoftware.hunterserver.repositories.ChestRepository;
import com.awakensoftware.hunterserver.repositories.TreasureRepository;
import com.awakensoftware.hunterserver.serverentities.Chest;
import com.awakensoftware.hunterserver.serverentities.Treasure;
import com.awakensoftware.hunterserver.utilities.geometry.GeometryHelper;
import com.awakensoftware.hunterserver.utilities.geometry.LengthUnit;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;

// Not sure if this needs to be a singleton
@Service("chestService")
@Scope("singleton")
@Transactional
public class ChestService extends ServerEntityServiceBase<Chest> {

	@Autowired
	private ChestRepository chestRepository;;

	@Autowired
	private TreasureRepository treasureRepository;

	public Chest create(String name) throws EntityException {
		Chest chest = new Chest();
		chest.setName(name);

		if (chest.validate()) {
			chestRepository.create(chest);
		} else {
			throw new EntityValidationFailureException();
		}
		return chest;
	}

	public Chest create(String name, double xLongitude, double yLatitude) throws EntityValidationFailureException {
		Chest chest = new Chest();
		chest.setName(name);

		Point point = GeometryHelper.createPoint(xLongitude, yLatitude);
		chest.setLocationPoint(point);

		if (chest.validate()) {
			chestRepository.create(chest);
		} else {
			throw new EntityValidationFailureException();
		}
		return chest;
	}

	public Chest addTreasureToChest(Chest chest, Treasure treasure) throws EntityException {
		chest.addTreasure(treasure);
		treasure.setChest(chest);

		if (chest.validate()) {
			chestRepository.update(chest);
			treasureRepository.update(treasure);
		} else {
			throw new EntityValidationFailureException();
		}
		return chest;
	}

	@Transactional(readOnly = true)
	public List<Chest> search(String text) {
		return chestRepository.searchByName(text);
	}

	// it would be nice if the high level can also tell the user how far each
	// chest is from the current location.
	@Transactional(readOnly = true)
	public List<Chest> searchNearbyChests(double xLongitude, double xLatitude, double radiusValue, LengthUnit radiusUnit) {
		// TODO: need to make sure radiusMeters is below the max allow range we
		// will set
		Geometry geometry = GeometryHelper.createCircle(xLongitude, xLatitude, radiusValue, radiusUnit);
		return chestRepository.searchNearbyChests(xLongitude, xLatitude, geometry);
	}

}
